package AIColorUSAStates;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;

public class Graph {
	
	public enum FirstColorType
	{
		Random,
		MostContraints
	}
	
	
	static final File FILEPATH = new File(System.getProperty("user.dir") + "/Session3/States and Borders.txt");
	
	public static CustomArrayList<Node> allNodesInGraph = new CustomArrayList<Node>();
	
	public static void createGraphWithUSAStates(FirstColorType type)
	{
		Graph.allNodesInGraph.clear();
		
		if (type == FirstColorType.Random)
		{
			Graph.createGraphRandomColor();
		}
		else if (type == FirstColorType.MostContraints)
		{
			createGraphMostContraintsFirst();
		}
	}
	
	private static void createGraphRandomColor()
	{
		HashMap<String, String[]> statesAndBorders = Graph.readStatesAndBorders();
		
		for (String state : statesAndBorders.keySet()) 
		{
			// Key contains a new State.
			Node newStateNode = Graph.allNodesInGraph.getNode(state);
			
			if (newStateNode == null)
			{
				newStateNode = new Node(Node.getRandomColor());
				newStateNode.Name = state;
				Graph.allNodesInGraph.add(newStateNode);
			}
			
			if (statesAndBorders.get(state) != null)
			{
				// Values are Neighbours
				for (String neiState : statesAndBorders.get(state)) 
				{
					Node neiNode = Graph.allNodesInGraph.getNode(neiState);
					
					if (neiNode == null)
					{
						neiNode = new Node(Node.getRandomColor());
						neiNode.Name = neiState;
						neiNode.setNewNeighbour(newStateNode);
						Graph.allNodesInGraph.add(neiNode);
					}
					else if (!neiNode.getNeighbours().contains(newStateNode))
					{
						neiNode.setNewNeighbour(newStateNode);
					}
					
					if (!newStateNode.getNeighbours().contains(neiNode))
					{
						newStateNode.setNewNeighbour(neiNode);
					}
				}
			}
		}
	}
	
	private static void createGraphMostContraintsFirst()
	{
		HashMap<String, String[]> statesAndBorders = Graph.readStatesAndBorders();
		
		// Generate Graph with uncolered nodes
		for (String state : statesAndBorders.keySet()) 
		{
			// Key contains a new State.
			Node newStateNode = Graph.allNodesInGraph.getNode(state);
			
			if (newStateNode == null)
			{
				newStateNode = new Node((byte) 0);
				newStateNode.Name = state;
				Graph.allNodesInGraph.add(newStateNode);
			}
			
			if (statesAndBorders.get(state) != null)
			{
				// Values are Neighbours
				for (String neiState : statesAndBorders.get(state)) 
				{
					Node neiNode = Graph.allNodesInGraph.getNode(neiState);
					
					if (neiNode == null)
					{
						neiNode = new Node((byte) 0);
						neiNode.Name = neiState;
						neiNode.setNewNeighbour(newStateNode);
						Graph.allNodesInGraph.add(neiNode);
					}
					else if (!neiNode.getNeighbours().contains(newStateNode))
					{
						neiNode.setNewNeighbour(newStateNode);
					}
					
					if (!newStateNode.getNeighbours().contains(neiNode))
					{
						newStateNode.setNewNeighbour(neiNode);
					}
				}
			}
		}
		
		// Select first node 
		Node mostCon = Graph.allNodesInGraph.getNodeWithMaxConstraints(false);
		mostCon.Color = Node.getRandomColor();
		
		// Now set initial colors
		for (int i = 1; i < Graph.allNodesInGraph.size(); i++) 
		{
			mostCon = Graph.allNodesInGraph.getNodeWithMaxConstraints(true);
			
			// Is mostCon null, different graphs exists
			if (mostCon == null)
				mostCon = Graph.allNodesInGraph.getNodeWithMaxConstraints(false);
			
			mostCon.Color = mostCon.getColorWithMinimumCollisionen();
		}
		
	}
	
	private static HashMap<String, String[]> readStatesAndBorders()
	{
		HashMap<String, String[]> statesAndBorders = new HashMap<String, String[]>(); 
		BufferedReader reader = null;
		
		try 
        {
			reader = new BufferedReader(new FileReader(FILEPATH));
	        
	        String input;        
        
	        // Read input file
			while( (input = reader.readLine()) != null ) 
			{
				String[] line = input.split(",");
				
				if (line.length > 1)
				{
					String[] neiArray = new String[line.length - 1];
					for (int i = 1; i < line.length; i++) 
					{
						neiArray[i - 1] = line[i];
					}
					statesAndBorders.put(line[0], neiArray);
				}
				else 
				{
					statesAndBorders.put(line[0], null);
				}
			}
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		
		
        try
        {
			reader.close();
		} 
        catch (IOException e) 
        {
			e.printStackTrace();
		}
        
        return statesAndBorders;
	}
}
